#ifndef _SGF_Game_H_
#define _SGF_Game_H_

#include "fastsig/fastsig.hpp"
#include <OIS/OIS.h>

namespace SGF
{
	struct KeyEvent
	{
		KeyEvent(const OIS::KeyEvent& ev)
			:key(ev.key),text(ev.text)
		{}
		OIS::KeyCode key;
		unsigned int text;
	};

	struct MouseEvent
	{
		MouseEvent(const OIS::MouseEvent& ev,OIS::MouseButtonID buttonID)
			:mouseState(ev.state),buttonID(buttonID)
		{}
		const OIS::MouseState& mouseState;
		const OIS::MouseButtonID buttonID;
	};

	class IGameState;
	class MapFactoryBase;

	class SGF_API Game:public Ogre::FrameListener,public OIS::KeyListener, public OIS::MouseListener
	{
	public:
		Game();
		virtual ~Game();
		static Game* getInstance();

		IGameState* getCurrentState() const;
		void changeState(IGameState* newState);
		virtual void changeMap(const char* newMap);

		virtual bool initialize();
		virtual void run();
		void quit();
		Ogre::Root* getOgreRoot() const;
		Ogre::RenderWindow* getRenderWindow() const;
		MapFactoryBase* getMapFactory() const;
		OIS::InputManager* getInputManager() const;
		OIS::Mouse* getMouse() const;
		OIS::Keyboard* getKeyboard() const;

		fastsig::signal<void(const KeyEvent&)> keyPressedSignal;
		fastsig::signal<void(const KeyEvent&)> keyReleasedSignal;
		fastsig::signal<void(const MouseEvent&)> mousePressedSignal;
		fastsig::signal<void(const MouseEvent&)> mouseReleasedSignal;
		fastsig::signal<void(const MouseEvent&)> mouseMovedSignal;

	private:
		virtual bool initializeOgre();
		virtual void initializeOIS();
		virtual void createMapFactory();

		virtual bool frameStarted(const Ogre::FrameEvent& ev);
		virtual bool frameEnded(const Ogre::FrameEvent& ev);
		virtual bool keyPressed( const OIS::KeyEvent &arg );
		virtual bool keyReleased( const OIS::KeyEvent &arg );
		virtual bool mouseMoved( const OIS::MouseEvent &arg );
		virtual bool mousePressed( const OIS::MouseEvent &arg, OIS::MouseButtonID id );
		virtual bool mouseReleased( const OIS::MouseEvent &arg, OIS::MouseButtonID id );

		bool running;
		MapFactoryBase* mapFactory;
		IGameState* currentState;
		Ogre::Root* root;
		Ogre::RenderWindow* window;
		OIS::InputManager* inputManager;
		OIS::Mouse* mouse;
		OIS::Keyboard* keyboard;

		static Game* instance;
	};
}

#endif